﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using ProjectBase.Core;

using $prjsn$.Entity;
using $prjsn$.Common;
using $prjsn$.Common.Business.Services;
using $prjsn$.Entity.Services;

namespace $safeprojectname$.CodeLists.Services
{
    /// <summary>
    /// This TEST class is derived from base EntityTestBase with template 'T'.
    /// and is directly equipped with two properties:
    /// 'Facade' of type IArticleGroupFacade - already lazily created and supplied with
    /// 'Messages' of type IList of ApplicationMessage; - for information exchange.
    /// Next steps should be:
    ///
    /// 1) implement the 'MakeItValid' method, use it for testing of 'working' entities
    /// 2) adjust Create, Update and Delete tests
    /// 3) append your new specific ones
    /// </summary>
    [TestClass]
    public class ArticleGroupTest : EntityTestBase<IArticleGroupFacade>
    {
        #region MakeItValid

        /// <summary>
        /// RE-use. Let's this method converts any entity into valid one (once)
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected virtual ArticleGroup MakeItValid(ArticleGroup entity)
        {
            Messages.Clear();
            entity = entity ?? Facade.CreateNew(); // FACTORY METHOD design pattern

            // TODO - fill needed properties to meet the Business rules
            entity.Code = "Test1" + Guid.NewGuid();
            entity.Description = entity.Code;
            entity.IsVisible = true;

            return entity;
        }

        #endregion MakeItValid

        #region Get

        /// <summary>
        /// Try to test your filtering criteria as much as possible.
        /// Check correctnes of the ArticleGroupSearch and ArticleGroupDao objects
        /// </summary>
        [TestMethod]
        public void Find()
        {
            var filter = new CodeListFilter()
            {
                Code = "Any", // TODO fix it
                TakeRows = 1,
            };
            var result = Facade.Find(filter);
            Assert.IsTrue(result.Count() > 0, " there must be ArticleGroup entity which meets provided filtering criteria ");
        }

        #endregion Get

        #region Set

        /// <summary>
        /// Firstly tries to store 'from-the-business-point-of-view' incorrect
        /// ArticleGroup entity - to get an Error Message.
        /// Secondly MakesItValid to assure the this will be stored
        /// </summary>
        [TestMethod]
        public void NewArticleGroup()
        {
            Messages.Clear();
            //   I. Ask Facade to get new (pre-filled but not valid - e.g. Code is missing)
            var entity = Facade.CreateNew();
            entity.Description = null;

            //  II. Assure that Facade won't allow to store this
            entity = Facade.Add(entity);
            Assert.IsTrue(entity.IsTransient());
            Assert.IsTrue(Messages.ContainsError());

            // III. Make entity valid
            Messages.Clear();
            entity = MakeItValid(entity);

            //  IV. Assure that valid will be stored
            entity = Facade.Add(entity);

            Assert.IsFalse(Messages.ContainsError(), Messages.GetErrorMessage());
            Assert.IsFalse(entity.IsTransient(), " MakeItValid was called, so 'ArticleGroup' Entity must be storable and NOT Transient now");
        }

        /// <summary>
        /// Tries to store similar Entity (e.g. with the same 'Code' property)
        /// to get the Error Message 'AlreadyExists'
        /// </summary>
        [TestMethod]
        public void AlreadyExistsArticleGroupCheck()
        {
            //   I. Get existing entity from DB
            var oldEntity = Facade.Find(new CodeListFilter() { TakeRows = 1 }).SingleOrDefault();
            if (oldEntity.IsNull())
            {
                Assert.Inconclusive(" To run this test there must be at least one 'ArticleGroup' entity in DB ");
                return;
            }

            //  II. Create new transient 'VALID' entity
            var entity = MakeItValid(null);

            // III. Set the property to get similar entities, which should be prohibited
            entity.Code = oldEntity.Code;

            //  IV. Call Facade to store new one
            Messages.Clear();
            entity = Facade.Add(entity);

            //   V. Facade must stop storing this
            Assert.IsTrue(entity.IsTransient());
            Assert.IsTrue(Messages.ContainsError());
        }

        /// <summary>
        /// Test that UPDATE checks are working
        /// Suggestion: try to store a demaged one, next as a valid ArticleGroup entity
        /// </summary>
        [TestMethod]
        public void UpdateArticleGroup()
        {
            // I. get existing
            var entity = Facade.Find(new CodeListFilter() { TakeRows = 1 }).SingleOrDefault();
            if (entity.IsNull())
            {
                Assert.Inconclusive(" there is no Entity record in DB Storage to test update");
                return;
            }

            // II. change it to get error
            Messages.Clear();

            // TODO change to get failures
            entity.Code = string.Empty;
            entity = Facade.Update(entity);

            // III. check there are errors
            Assert.IsTrue(Messages.ContainsError(), " There must be generated Error messages for not completely provided entity");

            Messages.Clear();
            // IV. repair it and check it will be stored

            entity = MakeItValid(entity);

            entity = Facade.Update(entity);
            // V. now it must be OK
            Assert.IsFalse(Messages.ContainsError(), Messages.GetErrorMessage());
        }

        #endregion Set

        #region InUse - Delete

        /// <summary>
        /// Essential TEST !!!!!
        /// !!!!!!!!!!!!!!!!!!!!
        ///
        /// Assure there, that ArticleGroup entity cannot be delted, when is used by another entity!
        /// It will help you! soon, you'll see...
        /// </summary>
        [TestMethod]
        public void IsArticleGroupInUse()
        {
            Messages.Clear();

            var holder1Facade = FacadeFactory.CreateFacade<IArticleFacade>();
            var holder1 = holder1Facade.Find(new ArticleFilter { TakeRows = 1 }).FirstOrDefault();
            Assert.IsTrue(holder1.Is(), "no Article to check a delete operation of the ArticleGroup");
            Assert.IsTrue(holder1.ArticleGroup.Is());

            Facade.Delete(holder1.ArticleGroup);
            Assert.IsTrue(Messages.ContainsError());
            Assert.IsTrue(Messages.Any(m => m.Template.Equals(Str.Messages.ItemIsUsedForEntity4)));
        }

        #endregion InUse - Delete

        #region Additional test attributes

        [ClassInitialize]
        public static void MyClassInitialize(TestContext testContext) { }

        [ClassCleanup]
        public static void MyClassCleanup() { }

        [TestInitialize]
        public override void MyTestInitialize() { base.MyTestInitialize(); }

        [TestCleanup]
        public override void MyTestCleanup() { base.MyTestCleanup(); }

        #endregion Additional test attributes
    }
}